﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Web.Mvc;

namespace Super.Common
{
   
    public static class EnumShowExtention
    {
       static private Dictionary<string, string> _cacheEnumShowDic = new Dictionary<string, string>();

       /// <summary>
       /// 输出枚举的ShowName，需要枚举声明EnumShowAttribute
       /// </summary>
       /// <param name="en">待输出的枚举</param>
       /// <returns></returns>
       static public string ToShow(this Enum en)
       {
           return ToShow(en, false, ",");
       }

       /// <summary>
       /// 输出枚举的ShowName，需要枚举声明EnumShowAttribute
       /// </summary>
       /// <param name="en">待输出的枚举</param>
       /// <param name="exceptionIfFail">未成功是否抛出异常</param>
       /// <param name="flagsSeparator">Flags类型输出时的间隔符</param>
       /// <returns></returns>
       static public string ToShow(this Enum en, bool exceptionIfFail, string flagsSeparator)
       {

         
           string showName;
           string enFullName = GetEnumFullName(en);

           // 先在缓存中找
           if (!_cacheEnumShowDic.TryGetValue(enFullName, out showName))
           {
               // 获取枚举类型
               Type enumType = en.GetType();

               // 查看其是否Flags
               object[] flagsAtts = enumType.GetCustomAttributes(typeof(FlagsAttribute), false);

               // 有Flags，按位处理，不缓存
               if (flagsAtts != null && flagsAtts.Length > 0)
               {
                   long currentVal = Convert.ToInt64(en);
                   StringBuilder sb = new StringBuilder();

                   string[] names = Enum.GetNames(enumType);
                   string zeroString = "";

                   foreach (string name in names)
                   {
                       long val = Convert.ToInt64(Enum.Parse(enumType, name));

                       // val为0，则跳过
                       if (val == 0)
                       {
                           object[] atts = enumType.GetField(name).GetCustomAttributes(typeof(EnumShowAttribute), false);
                           if (atts.Length > 0)
                           {
                               // 找到，设置
                               zeroString = ((EnumShowAttribute)atts[0]).ShowName;
                           }
                           continue;
                       }

                       // 比较
                       if ((val & currentVal) == val)
                       {
                           // 加间隔符
                           if (sb.Length != 0)
                           {
                               sb.Append(flagsSeparator);
                           }

                           // 加上定制特性值
                           object[] atts = enumType.GetField(name).GetCustomAttributes(typeof(EnumShowAttribute), false);
                           if (atts.Length > 0)
                           {
                               // 找到，设置
                               sb.Append(((EnumShowAttribute)atts[0]).ShowName);
                           }
                           else
                           {
                               // 没找到定制特性，参数指定抛出异常则抛出异常
                               if (exceptionIfFail)
                               {
                                   throw new InvalidOperationException(string.Format("此枚举{0}未定义EnumShowAttribute", enFullName));
                               }

                               sb.Append(name);
                           }
                       }
                   }

                   // 输出
                   if (sb.Length > 0)
                   {
                       return sb.ToString();
                   }
                   return zeroString;
               }
               // 无Flags



               else
               {

                   // 找字段
                   FieldInfo fieldInfo = enumType.GetField(en.ToString());
                   if (fieldInfo == null)
                   {
                       throw new InvalidOperationException(string.Format("非完整枚举{0}", enFullName));
                   }

                 
                  // var value=  (int)enumType.InvokeMember(fieldInfo.Name, BindingFlags.GetField, null, null, null);
                  
                   // 找定制特性
                   object[] atts = fieldInfo.GetCustomAttributes(typeof(EnumShowAttribute), false);
                   if (atts.Length > 0)
                   {
                       // 找到，设置
                       showName = ((EnumShowAttribute)atts[0]).ShowName;
                       lock (_cacheEnumShowDic)
                       {
                           _cacheEnumShowDic[enFullName] = showName;
                       }

                     
                   }
                   else
                   {
                       // 没找到定制特性，参数指定抛出异常则抛出异常
                       if (exceptionIfFail)
                       {
                           throw new InvalidOperationException(string.Format("此枚举{0}未定义EnumShowAttribute", enFullName));
                       }

                       // 否则直接输出本身的ToString
                       return en.ToString();
                   }
               }
           }

           return showName;
       }


  
       /// <summary>
       /// 获取枚举的全名
       /// </summary>
       /// <param name="en"></param>
       /// <returns></returns>
       static private string GetEnumFullName(Enum en)
       {
           return en.GetType().FullName + "." + en;
       }

       /// <summary>
       /// 给ListControl绑定枚举值
       /// </summary>
       static public IEnumerable<SelectListItem> GetItems(this Type enumType,object selectedValue=null)
       {
           if (!enumType.IsEnum)
           {
               throw new InvalidOperationException("类型必须是枚举:" + enumType.FullName);
           }
           IList<EnumShowExtention.SelectItem> listtemp = new List<EnumShowExtention.SelectItem>();
           // 获取枚举成员
           var values = Enum.GetValues(enumType);
           foreach (var item in values)
           {
               listtemp.Add(new EnumShowExtention.SelectItem { Value = ((int)item).ToString(), Text = ((Enum)item).ToShow() });
           }

           // 获取下拉框的数据源
           var list = new SelectList(listtemp, "Value", "Text", selectedValue);
           return list;
       }

        
        public class SelectItem
        {
            public string Value { get; set; }
            public string Text { get; set; }
        }

      /// <summary>
      /// 根据value获取 EnumShow 特性标签的值
      /// </summary>
      /// <param name="enumType"></param>
      /// <param name="value"></param>
      /// <param name="defaultString"></param>
      /// <returns></returns>
      public static string  GetItemShow(this Type enumType,int value,string defaultString=" ")
      {
           if (!enumType.IsEnum)
           {
               throw new InvalidOperationException("类型必须是枚举:" + enumType.FullName);
           }
      
          var values = Enum.GetValues(enumType);

          foreach (var item in values)
          {
              if((int)item==value)
              {
                 return ((Enum) item).ToShow();
              }
          }

          return defaultString;

      }

      /// <summary>
      /// 根据value获取 EnumShow 特性标签的值
      /// </summary>
      /// <param name="enumType"></param>
      /// <param name="value"></param>
      /// <param name="defaultString"></param>
      /// <returns></returns>
      public static string GetItemName(this Type enumType, int value, string defaultString = " ")
      {
          if (!enumType.IsEnum)
          {
              throw new InvalidOperationException("类型必须是枚举:" + enumType.FullName);
          }

          var values = Enum.GetValues(enumType);

          foreach (var item in values)
          {
              if ((int)item == value)
              {
                  return item.ToString();
              }
          }

          return defaultString;

      }
    }
}
